package com.zy.je.common.core.utils;

import com.zy.je.common.core.exception.BizException;
import com.zy.je.common.core.model.ICodeMessage;
import com.zy.je.common.core.utils.reflection.Fn;
import com.zy.je.common.core.utils.reflection.Reflection;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.JSONUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zy
 */
@Slf4j
public class CheckUtil {
//    /**
//     * 条件为真,则拋出异常
//     *
//     * @param condition
//     * @param errorMsg
//     * @throws BizException
//     */
//    @Deprecated
//    public static void check(boolean condition, ICodeMessage errorMsg) {
//        if (condition) {
//            throw new BizException(errorMsg);
//        }
//    }
//
//    /**
//     * 条件为真,则拋出异常
//     *
//     * @param condition
//     * @param errorMsg
//     * @throws BizException
//     */
//    @Deprecated
//    public static void check(boolean condition, ICodeMessage errorMsg, String description) {
//        if (condition) {
//            throw new BizException(errorMsg, description);
//        }
//    }

    /**
     * 条件为真,则拋出异常
     *
     * @param src
     * @param condition
     * @param errorMsg
     * @param logDesc
     * @throws BizException
     */
    public static void check(Object src, boolean condition, ICodeMessage<?> errorMsg, String logDesc) {
        checkAndLog(src, condition, errorMsg, logDesc);
    }

    private static void checkAndLog(Object src, boolean condition, ICodeMessage<?> errorMsg, String desc) {
        if (condition) {
            String msg = errorMsg.getMessage();
            if (!StringUtils.isBlank(desc)) {
                msg = msg + "（" + desc + "）";
            }
            log.warn("{}:{}", msg, toJsonStr(src));
            throw new BizException(errorMsg,desc);
        } else {
            if (log.isDebugEnabled()) {
                log.debug("{}",toJsonStr(src));
            }
        }
    }

    private static String toJsonStr(Object src) {
        try {
            return JSONUtil.toJsonStr(src);
        } catch (Exception ignored) {
        }
        return null;
    }


    /**
     * 对象为null，集合为空，字串符为blank，则抛出异常
     *
     * @param obj
     * @param errorMsg
     * @throws BizException
     */
    public static void checkBlank(Object obj, ICodeMessage<?> errorMsg) {
        checkAndLog(obj, isBlank(obj), errorMsg, null);
    }

    /**
     * 对象为null，集合为空，字串符为blank，则抛出异常
     *
     * @param obj
     * @param errorMsg
     * @throws BizException
     */
    public static void checkBlank(Object obj, ICodeMessage<?> errorMsg, String logDesc) {
        checkAndLog(obj, isBlank(obj), errorMsg, logDesc);
    }

    /**
     * 对象为null，集合为空，字串符为blank，则抛出异常
     *
     * @param obj
     * @param errorMsg
     * @throws BizException
     */
    @SafeVarargs
    public static <T, F extends Fn<T, ?>> void checkBlank(T obj, ICodeMessage<?> errorMsg, F... fn) {
        checkBlank(obj, errorMsg, null, fn);
    }
    /**
     * 对象为null，集合为空，字串符为blank，则抛出异常
     *
     * @param objList
     * @param fn
     * @param <T>
     */
    @SafeVarargs
    public static <T> void checkBlank(List<T> objList, ICodeMessage<?> errorMsg, Fn<T, ?>... fn) {
        CheckUtil.checkBlank(objList, errorMsg);
        final int[] i = {1};
        String msg = isBlank(errorMsg) ? "序号" : errorMsg.getMessage() + "，序号";
        objList.forEach(obj -> {
            checkBlank(obj, errorMsg, msg + i[0] + "。", fn);
            i[0] = i[0] + 1;
        });
    }

    @SafeVarargs
    public static <T, F extends Fn<T, ?>> void checkBlank(T obj, ICodeMessage<?> errorMsg, String desc, F... fn) {
        CheckUtil.checkBlank(obj, errorMsg);
        List<String> fieldNames = new ArrayList<>();
        for (F f : fn) {
            Object o = f.apply(obj);
            if (CheckUtil.isBlank(o)) {
                fieldNames.add(Reflection.fnToFieldName(f));
            }
        }
        checkAndLog(obj, !fieldNames.isEmpty(), errorMsg, (null == desc ? "" : desc) + String.join(",", fieldNames));
    }

    @SafeVarargs
    public static <T, F extends Fn<T, ?>> boolean isBlankAny(T obj, F... fn) {
        if (isBlank(obj)) {
            return true;
        }
        for (int i = 0; i < fn.length; ++i) {
            Object o = fn[i].apply(obj);
            if (isBlank(o)) {
                return true;
            }
        }
        return false;
    }

    @SafeVarargs
    public static <T, F extends Fn<T, ?>> boolean isBlankAll(T obj, F... fn) {
        if(!isBlank(obj) && isBlank(fn)){
            //目标对像不为空，且无待检测字段
            return false;
        }
        if(!isBlank(obj) ){
            for (int i = 0; i < fn.length; ++i) {
                Object o = fn[i].apply(obj);
                if (!isBlank(o)) {
                    //目标对像不为空，且待检测字段存在不为空
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 判读是否 对象为null，集合为空，字串符为blank
     *
     * @param obj
     * @return
     */
    public static boolean isBlank(Object obj) {
        if (ObjUtil.isEmpty(obj)) {
            return true;
        } else {
            if (obj instanceof CharSequence) {
                return StrUtil.isBlank((CharSequence) obj);
            } else {
                return false;
            }
        }
    }

//    public static void main(String[] args) {
//        LoginUser nnnn = LoginUser.builder()
//                .userName("nnnn")
//                .build();
//        boolean blankAll = isBlankAll(nnnn,LoginUser::getId,LoginUser::getUserName);
//        log.debug("blankAll={}",blankAll);
//    }
}
